﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace Simulation.Framework
{
    public class Log : MonoBehaviour
    {
        public static bool isClosed { get; set; } = false;
        public static bool isDraw { get; set; } = false;

        private static Log _instance;
        private static string newMsg = string.Empty;

        private static List<MsgContent> msgCache = new List<MsgContent>();

        private static GUIStyle logStyle;
        private static GUIStyle warningStyle;
        private static GUIStyle errorStyle;
        private static GUIStyle toggleStyle;

        private static Vector2 scrollPos;
        private static bool logToggle = true;
        private static bool warningToggle = true;
        private static bool errorToggle = true;

        private const ushort none = 0;
        private const ushort log = 1;
        private const ushort warning = 2;
        private const ushort error = 3;

        public static Log Init() {
            if (_instance == null)
            {
                _instance = Object.FindObjectOfType<Log>();
                
            }

            if (_instance == null) {
                GameObject go = new GameObject("Log");
                _instance = go.AddComponent<Log>();
                DontDestroyOnLoad(go);
            }

            return _instance;
        }

        public static void Clear() {
            if (_instance)
                Object.Destroy(_instance.gameObject);
            _instance = null;
        }

        public static void Info(object msg)
        {
            if (!isClosed)
            {
                string message = "[" + System.DateTime.Now + "]" + msg.ToString();
                Debug.Log(message);
                AddMsg(message, log);
            }
        }

        public static void Error(object msg)
        {
            if (!isClosed)
            {
                string message = "[" + System.DateTime.Now + "]" + msg.ToString();
                Debug.LogError(message);
                AddMsg(message, error);
            }
        }

        public static void Warning(object msg)
        {
            if (!isClosed)
            {
                string message = "[" + System.DateTime.Now + "]" + msg.ToString();
                Debug.LogWarning(message);
                AddMsg(message, warning);
            }
        }

        private void Awake()
        {
            int fontSize = 20;

            logStyle = new GUIStyle();
            logStyle.fontSize = fontSize;
            logStyle.alignment = TextAnchor.UpperLeft;
            logStyle.normal.textColor = Color.green;

            warningStyle = new GUIStyle();
            warningStyle.fontSize = fontSize;
            warningStyle.alignment = TextAnchor.UpperLeft;
            warningStyle.normal.textColor = Color.yellow;

            errorStyle = new GUIStyle();
            errorStyle.fontSize = fontSize;
            errorStyle.alignment = TextAnchor.UpperLeft;
            errorStyle.normal.textColor = Color.red;

            toggleStyle = new GUIStyle();
            toggleStyle.fontSize = fontSize;
            toggleStyle.normal.textColor = Color.white;
        }

        private void OnDestroy()
        {
            logStyle = null;
            warningStyle = null;
            errorStyle = null;
        }

        private void OnGUI()
        {
            if (isDraw == false || isClosed == true)
                return;

            GUILayout.BeginArea(new Rect(0,0,Screen.width * 0.75f * 0.25f, Screen.height * 0.25f));

            // toggle
            GUILayout.BeginHorizontal();
            logToggle = GUILayout.Toggle(logToggle, "log");
            warningToggle = GUILayout.Toggle(warningToggle, "warning");
            errorToggle = GUILayout.Toggle(errorToggle, "error");
            GUILayout.EndHorizontal();

            scrollPos = GUILayout.BeginScrollView(scrollPos);
            for (int i = 0; i < msgCache.Count; i++)
            {
                MsgContent content = msgCache[i];
                if (content.msgType == log && logToggle)
                    GUILayout.Label(content.msg, logStyle);
                else if (content.msgType == warning && warningToggle)
                    GUILayout.Label(content.msg, warningStyle);
                else if (content.msgType == error && errorToggle)
                    GUILayout.Label(content.msg, errorStyle);
            }
            GUILayout.EndScrollView();
            GUILayout.EndArea();

        }

        private static void AddMsg(string msg,ushort messageType) {
            if (msgCache == null)
                msgCache = new List<MsgContent>();
            if (msgCache.Count > 500) {
                msgCache.RemoveAt(0);
            }
            msgCache.Add(new MsgContent() { msgType = messageType, msg = msg });
            scrollPos.y = 100000;
        }

        private struct MsgContent {
            public ushort msgType;
            public string msg;
        }
    }
}
